﻿using Microsoft.AspNetCore.Mvc;
using ZR.Admin.WebApi.Filters;
using ZR.Model.Dto.Business.ProductionControl;
using ZR.Model.Models.ProductionControl;
using ZR.Service.IService.ProductionControl;
using ZR.Service.Service.ProductionControl;
using CKS.Core.Framework;
using CKS.PLC.Core.Cache;
using System.Diagnostics;
using MySqlX.XDevAPI;
//创建时间：2025-05-12
namespace ZR.Admin.WebApi.Controllers
{
    /// <summary>
    /// 工艺明细表
    /// </summary>
    [Verify]
    [Route("business/CksTechniqueDetails")]
    [ApiExplorerSettings(GroupName = "business")]
    public class CksTechniqueDetailsController : BaseController
    {
        /// <summary>
        /// 工艺明细表接口
        /// </summary>
        private readonly ICksTechniqueDetailsService _CksTechniqueDetailsService;

        public CksTechniqueDetailsController(ICksTechniqueDetailsService CksTechniqueDetailsService)
        {
            _CksTechniqueDetailsService = CksTechniqueDetailsService;
        }

        /// <summary>
        /// 查询工艺明细表列表
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        [HttpGet("list")]
        [ActionPermissionFilter(Permission = "ckstechniquedetails:list")]
        public IActionResult QueryCksTechniqueDetails([FromQuery] CksTechniqueDetailsQueryDto parm)
        {
            var response = _CksTechniqueDetailsService.GetList(parm);

            var client = _CksTechniqueDetailsService.AsSugarClient();
            var tech = client.Queryable<CksTechnique>().Where(a => a.Id == parm.TechniqueId).First();
            var template = client.Queryable<CksTechniqueTemplate>().Where(a => a.Id == tech.TemplateId).First();
            var allpoints = InternalApp.Fsql.Select<CksPlcDataPosition>().Where(a => a.PlcId == template.PlcId).ToList();

            var plcClient = ServiceCommon.PlcClients.ToList().Find(a => a.PlcInfo.Id == template.PlcId);
            var templates = client.Queryable<CksTechniqueTemplate>().Where(a => a.ParentId == tech.TemplateId).ToList();
            foreach (var data in response.Result)
            {
                var dataTemplate = templates.FirstOrDefault(a => a.Id == data.ItemTemplateId);
                if (dataTemplate != null)
                {
                    var p = allpoints.Find(a => a.BlockDb == template.ReadDB
                            && a.LinkActionId == template.SyncActionId
                            && a.DataId == dataTemplate.DataId);
                    if (p != null)
                    {
                        var val = plcClient.GetValue(p);
                        data.RunValue = $"{val ?? "Read Fail"}";
                    }
                    else
                    {
                        data.RunValue = $"未配置同步";
                    }
                }

            }



            return SUCCESS(response);
        }


        /// <summary>
        /// 查询工艺明细表详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpGet("{Id}")]
        [ActionPermissionFilter(Permission = "ckstechniquedetails:query")]
        public IActionResult GetCksTechniqueDetails(int Id)
        {
            var response = _CksTechniqueDetailsService.GetInfo(Id);

            var info = response.Adapt<CksTechniqueDetailsDto>();
            return SUCCESS(info);
        }

        /// <summary>
        /// 添加工艺明细表
        /// </summary>
        /// <returns></returns>
        [HttpPost()]
        [ActionPermissionFilter(Permission = "ckstechniquedetails:add")]
        [Log(Title = "工艺明细表", BusinessType = BusinessType.INSERT)]
        public IActionResult AddCksTechniqueDetails([FromBody] CksTechniqueDetailsDto parm)
        {
            var modal = parm.Adapt<CksTechniqueDetails>().ToCreate(HttpContext);

            var response = _CksTechniqueDetailsService.AddCksTechniqueDetails(modal);

            return SUCCESS(response);
        }

        // 设置最大并发数为2
        private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
        [HttpPost("AddCksTechniqueLog")]
        [ActionPermissionFilter(Permission = "ckstechniquedetails:add")]
        [Log(Title = "工艺下发", BusinessType = BusinessType.INSERT)]
        public IActionResult AddCksTechniqueLog([FromBody] AddCksTechniqueLogDto parm)
        {
            //
            // 尝试获取信号量，0表示不等待
            if (!_semaphore.Wait(0))
            {
                return ToResponse(ResultCode.FAIL, "请求过多，请稍后尝试");
            }
            Debug.WriteLine("Wait");

            try
            {
                var client = _CksTechniqueDetailsService.AsSugarClient();
                var tech = client.Queryable<CksTechnique>().Where(a => a.Id == parm.TechId).First();
                var details = client.Queryable<CksTechniqueDetails>()
                    .Where(a => a.TechniqueId == tech.Id).ToList();
                var vlist = details.Select(a => new { a.TechniqueId, a.Name, a.ItemTemplateId, a.Sequence, a.ConfigValue });
                Dictionary<string, object> body = new Dictionary<string, object>();
                body.Add("TechId", tech.Id);
                // body.Add("PlcId", tech.PlcId);
                //  body.Add("ActionId", tech.ToPlcActionId);
                body.Add("Details", vlist);

                var log = new CksTechniqueLog()
                {
                    Content = body.ToJson(),
                    CreatedTime = DateTime.Now,
                    TechniqueId = tech.Id,
                    Message = "",

                };
                //获取PLC实例进行写入操作，
                //写入完成更新log 以及 工艺的启用状态

                var template = client.Queryable<CksTechniqueTemplate>().Where(a => a.Id == tech.TemplateId).First();
                var allpoints = InternalApp.Fsql.Select<CksPlcDataPosition>().Where(a => a.PlcId == template.PlcId).ToList();

                var plcClient = ServiceCommon.PlcClients.ToList().Find(a => a.PlcInfo.Id == template.PlcId);


                var plc_point = allpoints.Find(a => a.EffectType == 7);
                var upper_point = allpoints.Find(a => a.ActionId == template.SendActionId && a.BlockDb == template.WriteDB);
                var tech_points = allpoints.FindAll(a => a.LinkActionId == template.SendActionId && a.BlockDb == template.WriteDB);
                if (plcClient == null)
                    return ToResponse(ResultCode.FAIL, "Plc编号错误");
                if (!plcClient.IsConnected)
                    return ToResponse(ResultCode.FAIL, "Plc未连接，无法下发");
                if (upper_point == null)
                    return ToResponse(ResultCode.FAIL, "缺少上位机下发信号");
                if (plc_point == null)
                    return ToResponse(ResultCode.FAIL, "缺少Plc确认信号");
                if (tech_points.Count == 0)
                    return ToResponse(ResultCode.FAIL, "未配置工艺参数信号");
                //查询信号表，判断是否配置了对应的action


                var ItemTemplates = client.Queryable<CksTechniqueTemplate>().Where(a => a.ParentId == tech.TemplateId).ToList();
                foreach (var item in details)
                {
                    var itt = ItemTemplates.Find(a => a.Id == item.ItemTemplateId);
                    item.S7Point = allpoints.Find(a => a.BlockDb == template.WriteDB && a.LinkActionId == template.SendActionId && a.DataId == itt.DataId);
                    if (item.S7Point == null)
                        return ToResponse(ResultCode.FAIL, "点位配置工具未配置相关点位");
                }


                //正式开始写入信号
                //先读取plc回复信号，若信号未复位，不可写入

                var confirm = plcClient.ReadInt16(plc_point.BlockDb, plc_point.BytePosition.ToInt());
                if (confirm == 1)
                    return ToResponse(ResultCode.FAIL, "上次发送，PLC信号未复位");
                var notify = plcClient.ReadInt16(upper_point.BlockDb, upper_point.BytePosition.ToInt());
                if (notify == 1)
                    return ToResponse(ResultCode.FAIL, "上次发送，PLC信号未确认");
                // 复位由逻辑： PLC确认信号 ，订阅执行信号的复位，这里无需额外处理
                foreach (var item in details)
                {
                    //if(item.S7Point.ParseType)
                    plcClient.SetValue(item.S7Point, item.ConfigValue);
                }
                plcClient.SetValue(upper_point, "1");
                log.Status = 10;
                log.OperName = HttpContext.GetName();
                var response = client.Insertable<CksTechniqueLog>(log).ExecuteCommand();

                //修改当前运行状态为启用，同plc同 action的其他工艺为禁用
                InternalApp.Fsql.Update<CksTechnique>().Set(a => a.Nullity, true)
                    .Where(a => a.TemplateId == template.Id).ExecuteAffrows();
                InternalApp.Fsql.Update<CksTechnique>().Set(a => a.Nullity, false)
                    .Set(a => a.LastSendTime, DateTime.Now)
                    .Where(a => a.Id == tech.Id).ExecuteAffrows();
                tech.LastSendTime = DateTime.Now;



                return SUCCESS(response);
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                // 释放信号量
                _semaphore.Release();
                Debug.WriteLine("Release");
            }
        }
        /// <summary>
        /// 同步工参数据项
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        [HttpPost("SyncCksTechnique")]
        public IActionResult SyncCksTechnique([FromBody] CksTechnique tech)
        {
            //查询模板项，遍历， 存在则更新，不存在则新增
            var client = _CksTechniqueDetailsService.AsSugarClient();

            var ItemTemplates = client.Queryable<CksTechniqueTemplate>().Where(a => a.ParentId == tech.TemplateId).ToList();
            foreach (var item in ItemTemplates)
            {
                var itemData = client.Queryable<CksTechniqueDetails>().Where(a => a.ItemTemplateId == item.Id && a.TechniqueId == tech.Id).First();
                if (itemData != null)
                {
                    itemData.Name = item.Name;
                    itemData.Sequence = item.Sequence;
                    itemData.DataId = item.DataId;
                    itemData.IsPrimary = item.IsPrimary;
                    client.Updateable(itemData).ExecuteCommand();
                }
                else
                {
                    itemData = new CksTechniqueDetails()
                    {
                        TechniqueId = tech.Id,
                        Name = item.Name,
                        ItemTemplateId = item.Id,
                        Sequence = item.Sequence,
                        DataId = item.DataId,
                        IsPrimary = item.IsPrimary
                    };
                    client.Insertable(itemData).ExecuteCommand();
                }
            }
            //删除模板中不存在的数据项
            var ids = ItemTemplates.Select(x => x.Id);
            var sql = client.Deleteable<CksTechniqueDetails>()
                 .Where(a => a.TechniqueId == tech.Id &&
                 !ids.Contains(a.ItemTemplateId)).ExecuteCommand();


            return SUCCESS(null);
        }


        [HttpPost("updateConfigValues")]
        public IActionResult UpdateConfigValues([FromBody] CksTechniqueDetailsBatchUpdateDto dto)
        {
            var client = _CksTechniqueDetailsService.AsSugarClient();

            foreach (var item in dto.Items)
            {

                client.Updateable<CksTechniqueDetails>()
                    .SetColumns(a => a.ConfigValue, item.RunValue)
                    .Where(a => a.Id == item.Id).ExecuteCommand();
            }
            return SUCCESS(null);
        }

        /// <summary>
        /// 更新工艺明细表
        /// </summary>
        /// <returns></returns>
        [HttpPut]
        [ActionPermissionFilter(Permission = "ckstechniquedetails:edit")]
        [Log(Title = "工艺明细表", BusinessType = BusinessType.UPDATE)]
        public IActionResult UpdateCksTechniqueDetails([FromBody] CksTechniqueDetailsDto parm)
        {
            var modal = parm.Adapt<CksTechniqueDetails>().ToUpdate(HttpContext);
            var response = _CksTechniqueDetailsService.UpdateCksTechniqueDetails(modal);

            return ToResponse(response);
        }

        /// <summary>
        /// 删除工艺明细表
        /// </summary>
        /// <returns></returns>
        [HttpDelete("delete/{ids}")]
        [ActionPermissionFilter(Permission = "ckstechniquedetails:delete")]
        [Log(Title = "工艺明细表", BusinessType = BusinessType.DELETE)]
        public IActionResult DeleteCksTechniqueDetails([FromRoute] string ids)
        {
            var idArr = Tools.SplitAndConvert<int>(ids);

            return ToResponse(_CksTechniqueDetailsService.Delete(idArr));
        }




    }
}